<?php defined('BASEPATH') OR exit('No direct script access allowed');
/**
 * Description: 验证码
 *
 * @author      Eden
 * @datetime    2016/11/30 19:22
 * @copyright   Beijing CmsTop Technology Co.,Ltd.
 */

class Sms_Model extends API_Model
{

    private $code = 0;

    /**
     * @var array 发送时间间隔
     */
    private $conf = array(
        'regist' => array(
            'key' => 'Regist',
            'lifeTime' => 60,       // 离下次发送的时间间隔
            'saveTime' => 600,      // 在缓存中保存的时间
        ),
        'bind' => array(
            'key' => 'Bind',
            'lifeTime' => 60,
            'saveTime' => 600
        ),
        'findpw' => array(
            'key' => 'Findpw',
            'lifeTime' => 60,
            'saveTime' => 600,
        ),
        'rebind' => array(
            'key' => 'Rebind',
            'lifeTime' => 60,
            'saveTime' => 600
        )
    );

    private $cacheConfig = array();
    private $key = '';


    /**
     * 初始化
     */
    public function __construct()
    {
        parent::__construct();
        $this->load->driver('cache');
    }

    /**
     * 主程序
     */
    public function run($params = array())
    {
        $send['state'] = false;
        do {
            $this->_checkParams($params);
            $phone = value($params, 'phone');
            $useAge = value($params, 'useAge');
            $useAge = strtolower($useAge);
            $this->key = $useAge;
            $this->cacheConfig = $this->conf[$useAge];
            if (empty($this->cacheConfig)) {
                $send['error'] = '无效类型';
                break;
            }
            $this->$useAge($phone);
        } while(false);
        $this->output->send($send);
    }

    /**
     * 重新绑定
     * @param $phone
     */
    public function rebind($phone)
    {
        $send['state'] = false;
        do {

            $key = 'API:Member:' . $this->cacheConfig['key'] . ':' . $phone;
            $this->_checkRepeat($key);
            if ($this->_checkPhoneExists($phone)) {
                $send['error'] = '用户已注册';
                break;
            }

            if ($this->_sendSms($phone)) {
                if ($this->_afterSucc($key)) {
                    $send['state'] = true;
                    $send['data'] = array(
                        'msg' => '发送成功',
                        'nextTime' => $this->cacheConfig['lifeTime'],
                        'saveTime' => $this->cacheConfig['saveTime']
                    );
                } else {
                    $send['error'] = $this->getError();
                }
            } else {
                $send['error'] = '发送失败';
            }


        } while(false);
        $this->output->send($send);
    }

    /**
     * 找回密码
     * @param $phone
     */
    public function findpw($phone)
    {
        $send['state'] = false;
        do {

            $key = 'API:Member:' . $this->cacheConfig['key'] . ':' . $phone;
            $this->_checkRepeat($key);
            if (!$this->_checkPhoneExists($phone)) {
                $send['error'] = '非注册用户';
                break;
            }

            if ($this->_sendSms($phone)) {
                if ($this->_afterSucc($key)) {
                    $send['state'] = true;
                    $send['data'] = array(
                        'msg' => '发送成功',
                        'nextTime' => $this->cacheConfig['lifeTime'],
                        'saveTime' => $this->cacheConfig['saveTime']
                    );
                } else {
                    $send['error'] = $this->getError();
                }
            } else {
                $send['error'] = '发送失败';
            }
        } while(false);
        $this->output->send($send);
    }

    /**
     * 重新绑定手机号
     * @param $phone
     */
    public function bind($phone)
    {
        $send['state'] = false;
        do {

            $key = 'API:Member:' . $this->cacheConfig['key'] . ':' . $phone;
            $this->_checkRepeat($key);
            if ($this->_sendSms($phone)) {
                // 发送成功
                if ($this->_afterSucc($key)) {
                    $send['state'] = true;
                    $send['data'] = array(
                        'msg' => '发送成功',
                        'nextTime' => $this->cacheConfig['lifeTime'],
                        'saveTime' => $this->cacheConfig['saveTime']
                    );
                } else {
                    $send['error'] = $this->getError();
                }
            } else {
                $send['error'] = '发送失败';
            }
        } while(false);
        $this->output->send($send);
    }

    /**
     * 缓存
     * @param $key
     * @return bool
     */
    private function _afterSucc($key)
    {
        try {
            return $this->cache->redis->save($key, array(
                'code' => $this->code,
                'lifeTime' => $this->cacheConfig['lifeTime'],
                'cacheTime' => time()
            ), $this->cacheConfig['saveTime']);
        } catch (Exception $e) {
            $this->setError('配置错误');
        }
        return false;
    }

    /**
     * 两次发送短信时间
     * @param $key
     * @return bool
     */
    private function _checkRepeat($key)
    {
        if ($cachedValue = $this->cache->redis->get($key)) {
            $lifeTime = $this->cacheConfig['lifeTime']; // 60 s
            $cacheTime = $cachedValue['cacheTime'];     // time()
            $nowTime = time();
            if ($nowTime - $cacheTime <= $lifeTime) {
                $send['state'] = false;
                $send['error'] = '发送频繁';
                $this->output->send($send);
                exit;
            }
        }
        return true;
    }

    /**
     * 注册时调用
     * @param $phone
     */
    public function regist($phone)
    {
        $send['state'] = false;
        do {
            $key = 'API:Member:'.$this->cacheConfig['key'].':' . $phone;
            $this->_checkRepeat($key);

            // 检查是否已经发送 1min
            if ($cachedValue = $this->cache->redis->get($key)) {
                $lifeTime = $this->cacheConfig['lifeTime']; // 60 s
                $cacheTime = $cachedValue['cacheTime'];     // time()
                if (time() - $cacheTime <= $lifeTime) {
                    $send['error'] = '发送频繁';
                    break;
                }
            }

            // 检查是否注册
            $this->_checkIfRegist($phone);
            if ($this->_sendSms($phone)) {
                // 缓存
                $res = $this->_afterSucc($key);
                if ($res) {
                    $send['state'] = true;
                    $send['data'] = array(
                        'msg' => '发送成功',
                        'nextTime' => $this->cacheConfig['lifeTime'],
                        'saveTime' => $this->cacheConfig['saveTime']
                    );
                    break;
                } else {
                    $send['error'] = $this->getError();
                    break;
                }
            }
            $send['error'] = '发送失败';
        } while(false);
        $this->output->send($send);
    }

    /**
     * sms.php
     */
    private function _sendSms($phone)
    {
        $this->config->load('sms');
        $sms_config = $this->config->item('sms');
        $this->load->library('util/Util_Sms', array(
            'template' => $sms_config['tpl']['regist']
        ), 'UtilSms');

        $this->code = rand(1000, 9999);
        if ($this->UtilSms->send($phone, array('{code}' => $this->code))) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 检查是否已经注册
     * @param $phone
     * @return bool
     */
    private function _checkIfRegist($phone)
    {
        $result = $this->_checkPhoneExists($phone);
        if ($result) {
            $this->output->send(array(
                'state' => false,
                'error' => '该手机号已注册'
            ));
            exit;
        }
        return true;
    }

    /**
     * 检查用户是否注册
     * @param $phone
     */
    private function _checkPhoneExists($phone)
    {
        $query = $this->db->get_where('user', array('phone' => $phone));
        return $query->row_array();
    }


    /**
     * 验证参数
     * @param $params
     * @return bool
     */
    private function _checkParams($params)
    {
        $send['state'] = false;
        do {

            if (empty($params['phone']) || !preg_match('/^1[34578]\d{9}$/', $params['phone'])) {
                $send['error'] = '手机号格式错误';
                break;
            }

            if (empty($params['useAge'])) {
                $send['error'] = '无效类型';
                break;
            }
            return true;
        } while(false);
        $this->output->send($send);
    }
}
